﻿using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace InterfaceDispatchTest
{
    interface IInterfaceA
    {
        void MethodA();
    }

    class ClassA1: IInterfaceA
    {
        [MethodImpl(MethodImplOptions.NoInlining)]
        public void MethodA()
        {
            Console.WriteLine("MethodA from ClassA1");
        }
    }

    class ClassA2: IInterfaceA
    {
        [MethodImpl(MethodImplOptions.NoInlining)]
        public void MethodA()
        {
            Console.WriteLine("MethodA from ClassA2");
        }
    }

    internal class Program
    {
        [MethodImpl(MethodImplOptions.NoInlining)]
        static void InterfaceDispatchTest(IInterfaceA v)
        {
            v.MethodA();
        }
        [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
        static void MainAlloc(int size)
        {
            var x = new byte[size];
        }
        [DllImport("*")]
        internal static extern void SetIcsNativeaotActiveCode(byte[] activeCode);
        static void Main(string[] args)
        {

            var activeCode = new byte[] { 0x18, 0x70, 0x51, 0x1A, 0xAA, 0x6C, 0xB5, 0x08, 0xBB, 0xC1, 0xD7, 0xAE, 0x70, 0xFE, 0xE4, 0x8F, 0x27, 0xD1, 0xED, 0x99, 0xD8, 0x8C, 0x70, 0xA8, 0x6C, 0xA3, 0x3D, 0xFA, 0x93, 0xCF, 0xB9, 0x66, };
            var platform = RuntimeInformation.ProcessArchitecture;
            if (platform == Architecture.Arm)
            {
                SetIcsNativeaotActiveCode(activeCode);
            }

            MainAlloc(1024 * 1024);
            var gcCollectThread = new System.Threading.Thread(() =>
            {
                while (true)
                {
                    System.Threading.Thread.Sleep(1000);
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    MainAlloc(1024 * 1024);
                    A();
                }
            });
            gcCollectThread.Start();
            IInterfaceA a1 = new ClassA1();
            IInterfaceA a2 = new ClassA2();
            InterfaceDispatchTest(a1);
            Console.WriteLine("Hello, World!");
        }
        static int a;
        static int b;
        static int c;
        static int d;
        static void A()
        {
            a += 1;
            B();
        }
        static void B()
        {
            b += 2;
            C();
        }
        static void C()
        {
            c+= 3;
            D();
        }
        static void D()
        {
            d += 4;
        }
    }
}
